home *** CD-ROM | disk | FTP | other *** search
/ 130 MIDI Tool Box / 130 MIDI Tool Box.iso / midimod1 / midimod.c < prev    next >
Text File  |  1993-04-13  |  36KB  |  1,385 lines

  1. /*
  2.  * MIDIMOD.C - Amiga Module to MIDI file converter
  3.  * Turbo C 2.0
  4.  *
  5.  * Description: Takes a .mod file and has a good go at converting it to
  6.  *              a .mid file. Equivalents to certain .mod samples can be
  7.  *              set to default to particular MIDI instruments. Multiple
  8.  *              MIDI instrument tables should be supported. Note that .mod
  9.  *              and .mid are at the end of the file.
  10.  *
  11.  * Author: Andrew Scott (Adrenalin Software)
  12.  *
  13.  * Date: 14/3/1993 ver 0.1
  14.  */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19.  
  20. #include <dos.h>
  21.  
  22. #include "textwin.h" /* Simple text-windowing environment */
  23. #include "midimod.h" /* Dialog/Info box messages and definitions */
  24.  
  25. #define ANOTE(x) ((x < 0) ? (-x) : (NoteValue(x)))
  26. #define ENOTE(x,y) ((sam->m > 127) ? (sam->m - 128) : (ANOTE(x) + sam->t[y]))
  27.  
  28. bfile MidFile, ModFile;
  29. char SongName[21];
  30. samps Samples;
  31. unsigned long PosLog[64];
  32. int PosI = 0;
  33. string MidFN, ModFN;
  34.  
  35. void OutByte(bfile f, char b)
  36. /* Post: The byte b has been written to the buffer of the file f */
  37. {
  38.     if (f->o == BUFFSIZE) {
  39.         fwrite(f->b, 1, BUFFSIZE, f->f);
  40.         f->o = 0;
  41.   }
  42.     f->b[f->o++] = b;
  43. }
  44.  
  45. void FlushOut(bfile f)
  46. /* Pre: f was opened for writing */
  47. /* Post: The file f has has its buffer flushed */
  48. {
  49.     if (f->o > 0)
  50.         fwrite(f->b, 1, f->o, f->f);
  51.     f->o = 0;
  52. }
  53.  
  54. void CloseOut(bfile f)
  55. /* Pre: f was opened for writing */
  56. /* Post: The file f has been flushed and is now closed */
  57. {
  58.     FlushOut(f);
  59.     fclose(f->f);
  60.     f->f = NULL;
  61. }
  62.  
  63. int OpenOut(bfile f, string fn)
  64. /* Returns: NZ if the file f has been opened for writing with the name fn */
  65. {
  66.     if (f->f != NULL)
  67.         CloseOut(f);
  68.     f->f = fopen(fn, "wb");
  69.     f->o = 0;
  70.     return f->f != NULL;
  71. }
  72.  
  73. unsigned long Beatle(bfile f)
  74. /* Returns: bfile-tell (btell=beatle). The offset from the start */
  75. {
  76.     return ftell(f->f) + f->o;
  77. }
  78.  
  79. unsigned char InByte(bfile f)
  80. /* Pre: f was opened for reading */
  81. /* Returns: The next byte from the file f */
  82. {
  83.     if (f->o == BUFFSIZE && !feof(f->f)) {
  84.         f->r = fread(f->b, 1, BUFFSIZE, f->f);
  85.         if (f->r < BUFFSIZE)
  86.             f->b[f->r] = 0;
  87.         f->o = 0;
  88.     }
  89.     if (f->o < f->r)
  90.          return f->b[f->o++];
  91.     return f->b[f->o];
  92. }
  93.  
  94. void CloseIn(bfile f)
  95. /* Post: The file f is now closed */
  96. {
  97.     fclose(f->f);
  98.     f->f = NULL;
  99. }
  100.  
  101. int OpenIn(bfile f, string fn)
  102. /* Returns: NZ if the file f has been opened for reading with the name fn */
  103. {
  104.     if (f->f != NULL)
  105.         CloseIn(f);
  106.     f->f = fopen(fn, "rb");
  107.     f->o = f->r = BUFFSIZE;
  108.     return f->f != NULL;
  109. }
  110.  
  111. void Inskipp(bfile f, unsigned long n) /* Stainless-steel rat for Pres */
  112. /* Pre: f was opened for reading */
  113. /* Post: f's file pointer has skipped forward n bytes */
  114. {
  115.     n += f->o;
  116.     while (n >= BUFFSIZE && !feof(f->f)) {
  117.         f->r = fread(f->b, 1, BUFFSIZE, f->f);
  118.         if (f->r < BUFFSIZE)
  119.             f->b[f->r] = 0;
  120.         n -= BUFFSIZE;
  121.     }
  122.     f->o = n; /* hmmm.. may cause an error if was eof.. X-fingers */
  123. }
  124.  
  125. struct bpos FPos(bfile f)
  126. /* Returns: All necessary information regarding file f's status */
  127. {
  128.     struct bpos x;
  129.  
  130.     x.d = *f;
  131.     x.p = ftell(f->f);
  132.     return x;
  133. }
  134.  
  135. void FGoto(bfile f, struct bpos x)
  136. /* Pre: x was the status of f previously */
  137. /* Post: File f has had its status changed to x */
  138. {
  139.     fseek(f->f, x.p, SEEK_SET);
  140.     *f = x.d;
  141. }
  142.  
  143. int WriteVLQ(bfile f, unsigned long i)
  144. /*
  145.  * Returns: # of bytes written after a variable-length-quantity equivalent
  146.  *    of i has been written to the file f.
  147.  */
  148. {
  149.     int x = 0;
  150.     unsigned long buffer;
  151.  
  152.     buffer = i & 127;
  153.     while ((i >>= 7) > 0)
  154.         buffer = ((buffer << 8) | 128) + (i & 127);
  155.     while (1) {
  156.         OutByte(f, buffer & 255);
  157.         x++;
  158.         if (buffer & 128)
  159.             buffer >>= 8;
  160.         else
  161.             return x;
  162.     }
  163. }
  164.  
  165. string InitFile(bfile f, string deffn, string t, int inpm)
  166. /* Returns: NULL if file is unacceptable, the filename otherwise. The
  167.  *    filename corresponds to file f, type t, with default filename deffn.
  168.  *    Will open an input file if inpm is NZ. deffn will be freed.
  169.  */
  170. {
  171.     int r = 0;
  172.     string newfn;
  173.  
  174.     _IF[1] = t;
  175.     newfn = DialogBox(_IF, deffn);
  176.     free(deffn);
  177.     if (! *newfn) {
  178.         free(newfn);
  179.         return NULL;
  180.     }
  181.     if (inpm)
  182.         r = OpenIn(f, newfn);
  183.     else if (fclose(fopen(newfn, "r"))==EOF || tolower(InfoBox(_OUTE))=='y')
  184.         r = OpenOut(f, newfn);
  185.     if (!r) {
  186.         free(newfn);
  187.         return NULL;
  188.     }
  189.     return newfn;
  190. }
  191.  
  192. int MKTest(bfile f)
  193. /* Returns: The number of samples in the Module file f */
  194. {
  195.     unsigned long offset;
  196.     int i = 15;
  197.     char s[4];
  198.  
  199.     offset = ftell(f->f);
  200.     if (!fseek(f->f, 1080, SEEK_SET)) {
  201.         fread(s, 1, 4, f->f);
  202.         if (!memcmp(s, "M.K.", 4) || !memcmp(s, "FLT",3))
  203.             i = 31;
  204.     }
  205.     fseek(f->f, offset, SEEK_SET);
  206.     return i;
  207. }
  208.  
  209. string SimplifyName(string s)
  210. /*
  211.  * Returns: A string similar to s, but has had any nasty headers removed
  212.  *    any leading spaces or trailing spaces, and all made lower-case
  213.  */
  214. {
  215.     string t, r, x;
  216.  
  217.     x = strchr(s, ':');
  218.     if (x != NULL && x-s == 5 && tolower(s[0])=='s' && tolower(s[1])=='t' &&
  219.      s[2]=='-') {
  220.         r = x = (string) malloc(18);
  221.         t = s + 6;
  222.         while (*(x++) = *(t++)); /* remove soundtracker header */
  223.     } else
  224.         r = strdup(s);
  225.     for (t = r; *t == ' '; t++);
  226.     x = r;
  227.     while (*(x++) = *(t++)); /* remove leading spaces */
  228.     t = strchr(r, ' ');
  229.     if (t != NULL)
  230.         *t = 0; /* remove 'trailing' spaces */
  231.     return strlwr((string) realloc(r, strlen(r) + 1));
  232. }
  233.  
  234. string GetLine(FILE *f)
  235. /* Returns: Next line from file f, NULL on error/eof */
  236. {
  237.     string s, t;
  238.     int c;
  239.  
  240.     if ((t = s = (string) malloc(MAXSTRING))==NULL) {
  241.         InfoBox(_OOME);
  242.         return NULL;
  243.     }
  244.     while ((c = fgetc(f)) != EOF && c != '\n')
  245.         *(t++) = c;
  246.     if (s == t) {
  247.         free(s);
  248.         return NULL;
  249.     }
  250.     *t = 0;
  251.     return (string) realloc(s, t-s+1);
  252. }
  253.  
  254. int ReadModSpecs(bfile f, string n, samps s)
  255. /*
  256.  * Returns: Z if f is not a supported Amiga Module, else n is set to
  257.  * be the name of the Module and s is set to hold sample information
  258.  */
  259. {
  260.     unsigned char b, c;
  261.     int i;
  262.     string t1;
  263.     samp *t2;
  264.  
  265.     for (i = 20, t1 = n; i--; *(t1++) = InByte(f));
  266.     *t1 = 0;
  267.     c = s->n = MKTest(f);
  268.     for (t2 = s->s; c--; t2++) {
  269.         for (i = 22, t1 = t2->n; i--; *(t1++) = InByte(f));
  270.         *t1 = 0;
  271.         b = InByte(f);
  272.         t2->l = 256 * b + InByte(f);
  273.         if (t2->l < 4)
  274.             t2->l = 0;   /* 6 bytes is pretty much a non-sample */
  275.         b = InByte(f);
  276.         t2->v = InByte(f);
  277.         InByte(f);
  278.         InByte(f);
  279.         b = InByte(f);
  280.         if (256 * b + InByte(f) > 1 && t2->l)
  281.             t2->l = -1;    /* looping: plays 'forever' */
  282.         t2->m = 0;
  283.         t2->t[0] = 0; /* set transposition values to 0 */
  284.         t2->t[1] = 0;
  285.         t2->t[2] = 0;
  286.     }
  287.     return !feof(f->f);
  288. }
  289.  
  290. int SetDefaults(samps s, string fn)
  291. /*
  292.  * Returns: NZ if the samples in s have been sucessfully allocated default
  293.  *    values corresponding to definitions in the DEF_MAPFILE file, and from
  294.  *    a .mm file corresponding to the filename fn
  295.  */
  296. {
  297.     FILE *f;
  298.     char i, m[MAXSTRING];
  299.     int d, e[3], v;
  300.     samp *sam;
  301.     string n, t;
  302.     bfile mmf;
  303.  
  304.     t = strchr(strcpy(m, fn), '.');
  305.     if (t==NULL) {
  306.         i = strlen(m);
  307.         m[i] = '.';
  308.     } else
  309.         i = t-m;
  310.     m[++i] = 'm';
  311.     m[++i] = 'm';
  312.     m[++i] = 0;
  313.     if (OpenIn(mmf, m)) {
  314.         for (i = s->n, sam = s->s; i--; sam++) {
  315.             sam->m = InByte(mmf);
  316.             sam->t[0] = (signed char) InByte(mmf);
  317.             sam->t[1] = (signed char) InByte(mmf);
  318.             sam->t[2] = (signed char) InByte(mmf);
  319.             InByte(mmf); /* volume data - not used */
  320.             InByte(mmf);
  321.             InByte(mmf);
  322.         }
  323.         CloseIn(mmf);
  324.     }
  325.     if ((f = fopen(DEF_MAPFILE, "rt"))==NULL) {
  326.         _NOFIL[3] = DEF_MAPFILE;
  327.         InfoBox(_NOFIL);
  328.         return 0;
  329.     }
  330.     i = s->n;
  331.     for (sam = s->s; i--; sam++)
  332.         if (sam->l) {
  333.             n = SimplifyName(sam->n);
  334.             t = GetLine(f);
  335.             sscanf(t, "%s %d %d %d %d", m, &d, &e[0], &e[1], &e[2]);
  336.             if ((v = strcmp(m, n))>0) {
  337.                 rewind(f);
  338.                 free(t);
  339.                 t = GetLine(f);
  340.                 sscanf(t, "%s %d %d %d %d", m, &d, &e[0], &e[1], &e[2]);
  341.                 v = strcmp(m, n);
  342.             }
  343.             free(t);
  344.             while (v < 0 && (t = GetLine(f)) != NULL) {
  345.                 sscanf(t, "%s %d %d %d %d", m, &d, &e[0], &e[1], &e[2]);
  346.                 free(t);
  347.                 v = strcmp(m, n);
  348.             }
  349.             if (!v) {
  350.                 sam->m = d;
  351.                 sam->t[0] = e[0];
  352.                 sam->t[1] = e[1];
  353.                 sam->t[2] = e[2];
  354.             }
  355.             free(n);
  356.         }
  357.     fclose(f);
  358.     return 1;
  359. }
  360.  
  361. void SaveDefaults(samps s, string fn)
  362. /*
  363.  * Post: The samples attributes in s have been written to a .mm file
  364.  *   corresponding to the filename fn
  365.  */
  366. {
  367.     char m[MAXSTRING];
  368.     string t;
  369.     char i;
  370.     bfile mmf;
  371.     samp *sam;
  372.  
  373.     t = strchr(strcpy(m, fn), '.');
  374.     if (t==NULL) {
  375.         i = strlen(m);
  376.         m[i] = '.';
  377.     } else
  378.         i = t-m;
  379.     m[++i] = 'm';
  380.     m[++i] = 'm';
  381.     m[++i] = 0;
  382.     if (!OpenOut(mmf, m))
  383.         return;
  384.     for (i = s->n, sam = s->s; i--; sam++) {
  385.         OutByte(mmf, sam->m);
  386.         OutByte(mmf, sam->t[0]);
  387.         OutByte(mmf, sam->t[1]);
  388.         OutByte(mmf, sam->t[2]);
  389.         OutByte(mmf, 0); /* Umm.. these bytes are reserved for implementing */
  390.         OutByte(mmf, 1); /* volume. If anyone wants to code a (v+x)*y/z bit */
  391.         OutByte(mmf, 1); /* for determining volume.. go ahead.              */
  392.     }
  393.     CloseOut(mmf);
  394. }
  395.  
  396. void NullArryFree(string *sp)
  397. /* Post: The NULL-terminated array sp is gone */
  398. {
  399.     string *t;
  400.  
  401.     t = sp;
  402.     while (*t != NULL)
  403.         free(*(t++));
  404.     free(sp);
  405. }
  406.  
  407. int Instrument()
  408. /* Returns: MIDI instrument selected from file DEF_INSFILE */
  409. {
  410.     static int w = 0, doff = -1;
  411.     static string *sp = NULL;
  412.     int c;
  413.  
  414.     if (sp == NULL) {
  415.         FILE *f;
  416.         string *t, s;
  417.         int x, i = 1;
  418.  
  419.         if ((f = fopen(DEF_INSFILE, "rt"))==NULL) {
  420.             _NOFIL[3] = DEF_INSFILE;
  421.             InfoBox(_NOFIL);
  422.             return -1;
  423.         }
  424.         if ((t = sp = (string *) malloc(257 * sizeof(string)))==NULL) {
  425.             InfoBox(_OOME);
  426.             return -1;
  427.         }
  428.         while ((s = GetLine(f)) != NULL)
  429.             if (x = strlen(s)) { /* ignore blank lines */
  430.                 i++;
  431.                 if (x > w)
  432.                     w = x;
  433.                 *(t++) = s;
  434.                 if (doff < 0 && *s=='D')  /* take note of first drum position */
  435.                     sscanf(s, "D%d ", &doff);
  436.             }
  437.         *t = NULL;
  438.         sp = (string *) realloc(sp, i * sizeof(string)); /* i <= 257 */
  439.         fclose(f);
  440.     }
  441.     c = ScrollChoice("MIDI Instruments", sp, w);
  442.     if (c>127)
  443.         c += doff;
  444.     return c;
  445. }
  446.  
  447. string MIDIVal(samp *sam)
  448. /* Returns: a string representing the MIDI instrument *sam */
  449. {
  450.     string s;
  451.  
  452.     s = (string) malloc(5);
  453.     if (sam->m < 128)
  454.         sprintf(s, "%4d", sam->m);
  455.     else
  456.         sprintf(s, "D%3d", sam->m - 128);
  457.     return s;
  458. }
  459.  
  460. string TransVal(samp *sam)
  461. /* Returns: a string representing the transpose amount of *sam */
  462. {
  463.     string s;
  464.  
  465.     s = (string) malloc(15);
  466.     if (!sam->t[1])
  467.         sprintf(s, "          %4d", sam->t[0]);
  468.     else if (!sam->t[2])
  469.         sprintf(s, "     %4d,%4d", sam->t[0], sam->t[1]);
  470.     else
  471.         sprintf(s, "%4d,%4d,%4d", sam->t[0], sam->t[1], sam->t[2]);
  472.     return s;
  473. }
  474.  
  475. string NullVal(samp *sam)
  476. /* Returns: an empty string */
  477. {
  478.     string s;
  479.  
  480.     *(s = (string) malloc(1)) = 0;
  481.     return s;
  482. }
  483.  
  484. int Sample(samps s, string (*MIDIVal)(samp *x), int w)
  485. /* Returns: Sample selected from list of samples, -1 on error */
  486. {
  487.     string *sp, *t, p;
  488.     samp *sam;
  489.     int i;
  490.  
  491.     if ((t = sp = (string *) malloc((s->n + 1) * sizeof(string)))==NULL) {
  492.         InfoBox(_OOME);
  493.         return -1;
  494.     }
  495.     for (i = s->n, sam = s->s; i--; sam++) {
  496.         *t = (string) malloc(25 + w);
  497.         p = MIDIVal(sam);
  498.         sprintf(*t, "%c%-22s %s", (sam->l) ? '*' : ' ', sam->n, p);
  499.         free(p);
  500.         t++;
  501.     }
  502.     *t = NULL;
  503.     i = ScrollChoice("Select Sample", sp, 24 + w);
  504.     NullArryFree(sp);
  505.     return i;
  506. }
  507.  
  508. int ChooseChannels(samps s)
  509. /*
  510.  * Returns: The number of different channels needed to play instruments. If
  511.  *    that number is not greater than 16, upto 16 channels will be allocated
  512.  *    to the samples.
  513.  */
  514. {
  515.     unsigned char c, d = 0, i[128], m, n, numchan;
  516.     samp *sam1, *sam2;
  517.  
  518.     n = s->n;
  519.     sam1 = s->s;
  520.     memset(i, 0, 128);
  521.     for (n = s->n, sam1 = s->s; n--; sam1++) {
  522.         sam1->c = -1;
  523.         if (sam1->l)
  524.             if (sam1->m > 127) {
  525.                 d = 1;
  526.                 sam1->c = DRUMCHANN;
  527.             } else
  528.                 i[sam1->m] = 1;
  529.         else
  530.             sam1->m = 0;
  531.     }
  532.     for (numchan = d, n = 128; n--; numchan += i[n]);
  533.     if (numchan > 16)
  534.         return numchan;
  535.     /* Ok.. now we must go through and set channels appropriately */
  536.     m = s->n;
  537.     sam1 = s->s;
  538.     c = 0;
  539.     while (m--) {
  540.         if (sam1->c < 0) {
  541.             sam1->c = c;
  542.             n = m;
  543.             sam2 = sam1 + 1;
  544.             while (n--) {
  545.                 if (sam2->c < 0)
  546.                     if (sam2->m == sam1->m || ! sam2->l)
  547.                         sam2->c = c;
  548.                 sam2++;
  549.             }
  550.             if (++c == DRUMCHANN && d)
  551.                 c++;
  552.         }
  553.         sam1++;
  554.     }
  555.     return numchan;
  556. }
  557.  
  558. void MapSamples(samps s)
  559. /* Post: The samples s have been allocated appropriate instruments, we hope */
  560. {
  561.     int i, j;
  562.  
  563.     do
  564.         if ((i = Sample(s, MIDIVal, 4))>=0 && (j = Instrument())>=0)
  565.             s->s[i].m = j;
  566.     while (i>=0);
  567. }
  568.  
  569. void SaveSamp(samp sam)
  570. /* Post: The sample sam has been updated in the DEF_MAPFILE file */
  571. {
  572.     FILE *f1, *f2;
  573.     string s, n;
  574.     int v, d, e[3];
  575.     char m[MAXSTRING];
  576.  
  577.     if (!sam.l)
  578.         return;
  579.     if ((f1 = fopen(DEF_MAPFILE, "rt")) == NULL) {
  580.         _NOFIL[3] = DEF_MAPFILE;
  581.         InfoBox(_NOFIL);
  582.         return;
  583.     }
  584.     f2 = fopen("temp.$$$", "wt");
  585.     n = SimplifyName(sam.n);
  586.     v = 1;
  587.     while (v > 0 && (s = GetLine(f1)) != NULL) {
  588.         sscanf(s, "%s %d %d %d %d", m, &d, &e[0], &e[1], &e[2]);
  589.         if ((v = strcmp(n, m)) <= 0) {
  590.             fprintf(f2, "%s %d %d %d %d\n", n, sam.m, sam.t[0], sam.t[1], sam.t[2]);
  591.             free(n);
  592.             n = NULL;
  593.             if (v)
  594.                 fprintf(f2, "%s\n", s);
  595.         } else
  596.             fprintf(f2, "%s\n", s);
  597.         free(s);
  598.     }
  599.     while ((s = GetLine(f1))!=NULL) {
  600.         fprintf(f2, "%s\n", s);
  601.         free(s);
  602.     }
  603.     if (n != NULL) {
  604.         fprintf(f2, "%s %d %d %d %d\n", n, sam.m, sam.t[0], sam.t[1], sam.t[2]);
  605.         free(n);
  606.     }
  607.     fclose(f2);
  608.     fclose(f1);
  609.     if (unlink(DEF_MAPFILE)<0 || rename("temp.$$$", DEF_MAPFILE)<0)
  610.         InfoBox(_NOSAV);
  611. }
  612.  
  613. void SaveSamples(samps s)
  614. /* Post: The desired sample attributes of s have been saved to disk */
  615. {
  616.     int i;
  617.  
  618.     do
  619.         if ((i = Sample(s, NullVal, 0))>=0)
  620.             SaveSamp(s->s[i]);
  621.     while (i>=0);
  622. }
  623.  
  624. void Transpositions(samps s)
  625. /* Post: All necessary transpositions have been applied to the samples s */
  626. {
  627.     int i;
  628.     string s2;
  629.  
  630.     do
  631.         if ((i = Sample(s, TransVal, 14))>=0) {
  632.             char s1[41];
  633.             samp *sam;
  634.  
  635.             sam = s->s + i;
  636.             if (!sam->t[1])
  637.                 sprintf(s1, "%d", sam->t[0]);
  638.             else if (!sam->t[2])
  639.                 sprintf(s1, "%d,%d", sam->t[0], sam->t[1]);
  640.             else
  641.                 sprintf(s1, "%d,%d,%d", sam->t[0], sam->t[1], sam->t[2]);
  642.             s2 = DialogBox(_TRAQ, s1);
  643.             sam->t[1] = 0;
  644.             sam->t[2] = 0;
  645.             sscanf(s2, "%d,%d,%d", &sam->t[0], &sam->t[1], &sam->t[2]);
  646.             free(s2);
  647.             if ((sam->t[0] || sam->t[1]) && sam->m > 127)
  648.                 InfoBox(_TRANWRN);
  649.             if (sam->t[0]<-128 || sam->t[0]>127 || sam->t[1]<-128 ||
  650.              sam->t[1]>127 || sam->t[2]<-128 || sam->t[2]>127) {
  651.                 InfoBox(_TRANE);
  652.                 sam->t[0] = 0;
  653.                 sam->t[1] = 0;
  654.                 sam->t[2] = 0;
  655.             }
  656.         }
  657.     while (i>=0);
  658. }
  659.  
  660. unsigned char NoteValue(unsigned int n)
  661. /* Returns: MIDI note equivalent of MOD period-lengths */
  662. {
  663.     static unsigned int t[72] = {
  664.         1712, 1616, 1525, 1440, 1357, 1281, 1209, 1141, 1077, 1017, 961, 907,
  665.         856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,
  666.         428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,
  667.         214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113,
  668.         107, 101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57,
  669.         53, 50, 48, 45, 42, 40, 38, 36, 34, 32, 30, 28
  670.         };
  671.     signed char a = 0, m = 35, b = 71;
  672.  
  673.     if (!n)
  674.         return 0;
  675.     for (; b-a > 1; m = (a + b) / 2) /* binary search */
  676.         if (t[m] < n)
  677.             b = m;
  678.         else
  679.             a = m;
  680.     if (n - t[b] < t[a] - n) /* choose closest value */
  681.         return b + 36;
  682.     return a + 36;
  683. }
  684.  
  685. unsigned long NoteLength(unsigned char n, unsigned int l, unsigned int b)
  686. /* Returns: # of ticks to play note length l at pitch n, b beats/min */
  687. {
  688.     static float t[84] = {
  689.         3.200e-3, 3.020e-3, 2.851e-3, 2.691e-3, 2.540e-3, 2.397e-3,
  690.         2.263e-3, 2.136e-3, 2.016e-3, 1.903e-3, 1.796e-3, 1.695e-3,
  691.         1.600e-3, 1.510e-3, 1.425e-3, 1.345e-3, 1.270e-3, 1.197e-3,
  692.         1.131e-3, 1.068e-3, 1.008e-3, 9.514e-4, 8.980e-4, 8.476e-4,
  693.         8.000e-4, 7.551e-4, 7.127e-4, 6.727e-4, 6.350e-4, 5.993e-4,
  694.         5.657e-4, 5.339e-4, 5.040e-4, 4.757e-4, 4.490e-4, 4.238e-4,
  695.         4.000e-4, 3.775e-4, 3.564e-4, 3.364e-4, 3.175e-4, 2.997e-4,
  696.         2.828e-4, 2.670e-4, 2.520e-4, 2.378e-4, 2.245e-4, 2.119e-4,
  697.         2.000e-4, 1.888e-4, 1.782e-4, 1.682e-4, 1.587e-4, 1.498e-4,
  698.         1.414e-4, 1.335e-4, 1.260e-4, 1.189e-4, 1.122e-4, 1.059e-4,
  699.         1.000e-4, 9.439e-5, 8.909e-5, 8.409e-5, 7.937e-5, 7.492e-5,
  700.         7.071e-5, 6.674e-5, 6.300e-5, 5.946e-5, 5.612e-5, 5.297e-5,
  701.         5.000e-5, 4.719e-5, 4.454e-5, 4.204e-5, 3.969e-5, 3.746e-5,
  702.         3.536e-5, 3.337e-5, 3.150e-5, 2.973e-5, 2.806e-5, 2.649e-5
  703.         }; /* multipliers for each pitch: 12th roots of 2 apart */
  704.  
  705.     return t[n - 36] * b * l; /* better not slide out of this range :( */
  706. }
  707.  
  708. void WriteHeader(bfile mf, unsigned char n)
  709. /* Post: The MIDI header has been written to mf, with #tracks = n */
  710. {
  711.     static unsigned char MIDIH[14] = {
  712.         77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, -1, 0, 192
  713.     };
  714.     int i = 0;
  715.  
  716.     MIDIH[11] = n+1;
  717.     while (i < 14)
  718.         OutByte(mf, MIDIH[i++]);
  719. }
  720.  
  721. unsigned int Trk0Info(bfile mf, string s)
  722. /*
  723.  * Returns: the number of bytes written as track 0 so far, given mf as the
  724.  *    output MIDI file. s is the name of the tune.
  725.  */
  726. {
  727.     static unsigned char TRK0I[63] = {
  728.         0, 255, 2, 42, 70, 105, 108, 101, 32, 67, 111, 112, 121, 114, 105, 103,
  729.         104, 116, 32, 40, 99, 41, 32, 49 ,57, 57, 51, 32, 65, 100, 114, 101, 110,
  730.         97, 108, 105, 110, 32, 83, 111, 102, 116, 119, 97, 114, 101,
  731.         0, 255, 88, 4, 3, 2, 24, 8,
  732.         0, 255, 89, 2, 0, 0,
  733.         0, 255, 3
  734.         }; /* standard header + copyright message */
  735.     unsigned int i = 0;
  736.  
  737.     while (i < 63)
  738.         OutByte(mf, TRK0I[i++]);
  739.     i = 64 + strlen(s);
  740.     OutByte(mf, strlen(s));
  741.     while (*s)
  742.         OutByte(mf, *(s++));
  743.     return i;
  744. }
  745.  
  746. void AddToLog(unsigned long a, unsigned long b)
  747. /* Post: a (file position) and b (number) have been added to the log */
  748. {
  749.     PosLog[PosI++] = b;
  750.     PosLog[PosI++] = a;
  751. }
  752.  
  753. void WriteLog(FILE *f)
  754. /* Post: PosLog has been written into file f */
  755. {
  756.     unsigned long x, y;
  757.     unsigned char c[4];
  758.  
  759.     if (!PosI)
  760.         return;
  761.     x = ftell(f);
  762.     while (PosI) {
  763.         fseek(f, PosLog[--PosI], SEEK_SET);
  764.         y = PosLog[--PosI];
  765.         c[3] = y & 255;
  766.         y >>= 8;
  767.         c[2] = y & 255;
  768.         y >>= 8;
  769.         c[1] = y & 255;
  770.         y >>= 8;
  771.         c[0] = y;
  772.         fwrite(c, 1, 4, f);
  773.     }
  774.     fseek(f, x, SEEK_SET);
  775. }
  776.  
  777. void ConvertMOD(bfile f1, bfile f2, string tn, samps smp)
  778. /*
  779.  * Post: The Amiga MODfile f1 has been converted and written to MIDI file f2,
  780.  *    using instrument mappings smp. Tune has a name tn.
  781.  */
  782. {
  783.     unsigned char b, length, pattern[128];
  784.     string n, t;
  785.     unsigned int i, j, k, tempdone = 0;
  786.     samp *sam;
  787.     struct bpos p1, p2;
  788.  
  789.     p1 = FPos(f1);
  790.     length = InByte(f1);
  791.     InByte(f1);
  792.     for (i = 0; i < 128; pattern[i++] = InByte(f1));
  793.     Inskipp(f1, (smp->n > 15) ? 4 : 0);
  794.     WriteHeader(f2, smp->n);
  795.     p2 = FPos(f1);
  796.     for (i = 0, sam = smp->s - 1; i <= smp->n; sam++, i++) {
  797.         unsigned long cnt, inst, timer, delay[4];
  798.         unsigned char c;
  799.  
  800.         OutByte(f2, 77);
  801.         OutByte(f2, 84);
  802.         OutByte(f2, 114);
  803.         OutByte(f2, 107);
  804.         inst = Beatle(f2); /* store this position so can set AFTERWARDS - hehe */
  805.         OutByte(f2, 0);
  806.         OutByte(f2, 0);
  807.         OutByte(f2, 0);
  808.         OutByte(f2, 0);
  809.         if (!i)
  810.             cnt = Trk0Info(f2, tn);
  811.         else {
  812.             OutByte(f2, 0);
  813.             OutByte(f2, 255);
  814.             OutByte(f2, 3);
  815.             b = strlen(n = sam->n);
  816.             OutByte(f2, b);
  817.             cnt = 7 + b;
  818.             while (b--)
  819.                 OutByte(f2, *(n++));
  820.             c = sam->c;
  821.             OutByte(f2, 0);
  822.             OutByte(f2, 0xC0 + c); /* set channel */
  823.             OutByte(f2, (sam->m > 127) ? 126 : sam->m);
  824.         }
  825.         timer = 0;
  826.         if (sam->l || !i) {
  827.             unsigned int bpm, ticks, l, effect, h;
  828.             unsigned char sampnum, vol[4];
  829.             signed char patbreak;
  830.             unsigned long x, pause;
  831.             int note, lastslide, slideto;
  832.             int n[4][48][2]; /* note data for a song position */
  833.             int lastn[4]; /* last note on a particular channel */
  834.  
  835.             sprintf(_CNVPOS[2]+7, "%d", i);
  836.             DrawBox(_CNVPOS);
  837.             memset(lastn, 0, 4 * sizeof(int));
  838.             memset(vol, 0, 4);
  839.             memset(delay, 0, 4 * sizeof(long));
  840.             bpm = 128;
  841.             ticks = 6;
  842.             lastslide = slideto = 0;
  843.             patbreak = 0;
  844.             for (h = 48; h--; )
  845.                 for (k = 4; k--; )
  846.                     n[k][h][0] = 0;
  847.             for (l = 0; l < length; l++) {
  848.                 if (pattern[l]<=pattern[l-1] || !l) {
  849.                     FGoto(f1, p2);
  850.                     x = (unsigned) 1024 * pattern[l];
  851.                 } else
  852.                     x = (unsigned) 1024 * (pattern[l]-pattern[l-1]-1);
  853.                 Inskipp(f1, x);
  854.                 j = 64;
  855.                 if (patbreak>0)
  856.                     patbreak = 1-patbreak;
  857.                 while (j--) {
  858.                     pause = 0;
  859.                     if (patbreak)
  860.                         Inskipp(f1, 16);
  861.                     else
  862.                         for (k = 0; k < 4; k++) {
  863.                             n[k][0][1] = sam->v;
  864.                             sampnum = InByte(f1);
  865.                             note = ((sampnum & 15) << 8) + InByte(f1);
  866.                             effect = InByte(f1);
  867.                             sampnum = (sampnum & ~15) + (effect >> 4);
  868.                             if (!i)
  869.                                 note = 0;
  870.                             if (note && delay[k]) { /* stop playing old note */
  871.                                 cnt += 3 + WriteVLQ(f2, timer);
  872.                                 timer = 0;
  873.                                 OutByte(f2, 0x80 + c); /* note off */
  874.                                 OutByte(f2, ENOTE(lastn[k], 0));
  875.                                 OutByte(f2, vol[k]);
  876.                                 if (sam->t[1]) {
  877.                                     cnt += 4;
  878.                                     OutByte(f2, 0);
  879.                                     OutByte(f2, 0x80 + c);
  880.                                     OutByte(f2, ENOTE(lastn[k], 1));
  881.                                     OutByte(f2, vol[k]);
  882.                                     if (sam->t[2]) {
  883.                                         cnt += 4;
  884.                                         OutByte(f2, 0);
  885.                                         OutByte(f2, 0x80 + c);
  886.                                         OutByte(f2, ENOTE(lastn[k], 2));
  887.                                         OutByte(f2, vol[k]);
  888.                                     }
  889.                                 }
  890.                                 delay[k] = 0;
  891.                             }
  892.                             if (sampnum != i)  /* don't do anything if wrong sample */
  893.                                 note = 0;
  894.                             n[k][0][0] = note;
  895.                             effect = ((effect & 15) << 8) + InByte(f1);
  896.                             switch (effect & 0xF00) {
  897.                                 case 0x000: { /* arpeggio */
  898.                                     int nv;
  899.  
  900.                                     if (!i || !effect || sam->m > 127)
  901.                                         break;
  902.                                     if (!note)
  903.                                         if (!delay[k])
  904.                                             break;
  905.                                         else {
  906.                                             nv = NoteValue(lastn[k]);
  907.                                             n[k][47][0] = lastn[k];
  908.                                             n[k][47][1] = vol[k];
  909.                                             if (effect & 0x0F0)
  910.                                                 n[k][16][0] = -(nv + ((effect & 0x0F0) >> 4));
  911.                                             n[k][16][1] = vol[k];
  912.                                             if (effect & 0x00F)
  913.                                                 n[k][32][0] = -(nv + (effect & 0x00F));
  914.                                             n[k][32][1] = vol[k];
  915.                                         }
  916.                                     else {
  917.                                         nv = NoteValue(note);
  918.                                         n[k][47][0] = note;
  919.                                         n[k][47][1] = sam->v;
  920.                                         if (effect & 0x0F0)
  921.                                             n[k][16][0] = -(nv + ((effect & 0x0F0) >> 4));
  922.                                         n[k][16][1] = sam->v;
  923.                                         if (effect & 0x00F)
  924.                                             n[k][32][0] = -(nv + (effect & 0x00F));
  925.                                         n[k][32][1] = sam->v;
  926.                                     }
  927.                                     break;
  928.                                     }
  929.                                 case 0x300: /* slide to */
  930.                                     if (!note && !slideto || note==lastn[k] || sam->m > 127)
  931.                                         break;
  932.                                     if (effect & 0x0FF)
  933.                                         lastslide = effect & 0x0FF;
  934.                                     else
  935.                                         lastslide = abs(lastslide);
  936.                                     if (note)
  937.                                         slideto = note;
  938.                                     if (slideto > lastn[k]) {
  939.                                         n[k][0][0] = lastn[k] + lastslide*(ticks-1);
  940.                                         if (n[k][0][0] > 856)
  941.                                             n[k][0][0] = 856;
  942.                                         if (n[k][0][0] > slideto)
  943.                                             n[k][0][0] = slideto;
  944.                                     } else {
  945.                                         n[k][0][0] = lastn[k] - lastslide*(ticks-1);
  946.                                         if (n[k][0][0] < 113)
  947.                                             n[k][0][0] = 113;
  948.                                         if (n[k][0][0] < slideto)
  949.                                             n[k][0][0] = slideto;
  950.                                     }
  951.                                     n[k][0][1] = vol[k];
  952.                                     break;
  953.                                 case 0x100: /* slide up */
  954.                                 case 0x200: /* slide down */
  955.                                     if (!(effect & 0x0FF) || sam->m > 127)
  956.                                         break;
  957.                                     if (effect & 0x200)
  958.                                         lastslide = effect & 0x0FF;
  959.                                     else
  960.                                         lastslide = -(effect & 0x0FF);
  961.                                     if (!note)
  962.                                         if (!delay[k])
  963.                                             break;
  964.                                         else {
  965.                                             n[k][0][0] = lastn[k] + lastslide;
  966.                                             n[k][0][1] = vol[k];
  967.                                         }
  968.                                     else
  969.                                         n[k][0][0] += lastslide;
  970.                                     if (n[k][0][0] > 856)
  971.                                         n[k][0][0] = 856;
  972.                                     else if (n[k][0][0] < 113)
  973.                                         n[k][0][0] = 113;
  974.                                     break;
  975.                                 case 0x400: /* vibrato */
  976.                                 case 0x700: /* tremolo */
  977.                                     /* ignore these effects.. not convertable */
  978.                                     break;
  979.                                 case 0x500: /* slide to & volume slide */
  980.                                     if ((note || slideto) && note!=lastn[k] && sam->m < 128) {
  981.                                         if (note)
  982.                                             slideto = note;
  983.                                         if (slideto > lastn[k]) {
  984.                                             n[k][0][0] = lastn[k] + lastslide*(ticks-1);
  985.                                             if (n[k][0][0] > 856)
  986.                                                 n[k][0][0] = 856;
  987.                                             if (n[k][0][0] > slideto)
  988.                                                 n[k][0][0] = slideto;
  989.                                         } else {
  990.                                             n[k][0][0] = lastn[k] - lastslide*(ticks-1);
  991.                                             if (n[k][0][0] < 113)
  992.                                                 n[k][0][0] = 113;
  993.                                             if (n[k][0][0] < slideto)
  994.                                                 n[k][0][0] = slideto;
  995.                                         }
  996.                                     } else
  997.                                         n[k][0][0] = 0;
  998.                                     note = 0;
  999.                                 case 0x600: /* vibrato & volume slide */
  1000.                                 case 0xA00: { /* volume slide */
  1001.                                     int v;
  1002.  
  1003.                                     if (!note)
  1004.                                         v = vol[k];
  1005.                                     else
  1006.                                         v = sam->v;
  1007.                                     v += 5*(effect & 0x0F0); /* can't set volume mid-note */
  1008.                                     v -= 5*(effect & 0x00F);
  1009.                                     if (v > 127)
  1010.                                         v = 127;
  1011.                                     else if (v < 0)
  1012.                                         v = 0;
  1013.                                     n[k][0][1] = v;
  1014.                                     break;
  1015.                                     }
  1016.                                 case 0x900: /* set offset: pretend it's retrigger */
  1017.                                     if ((!n[k][0][0] || !sampnum) && delay[k]) {
  1018.                                         n[k][0][0] = lastn[k];
  1019.                                         n[k][0][1] = vol[k];
  1020.                                     }
  1021.                                     break;
  1022.                                 case 0xB00: /* position jump: ignore, but break anyway */
  1023.                                     patbreak = 1;
  1024.                                     break;
  1025.                                 case 0xD00: /* pattern break */
  1026.                                     patbreak = 1 + effect & 0x0FF;
  1027.                                     break;
  1028.                                 case 0xC00: /* set volume */
  1029.                                     n[k][0][1] = effect & 0x0FF;
  1030.                                     break;
  1031.                                 case 0xF00: /* set tempo */
  1032.                                     bpm = effect & 0x0FF;
  1033.                                     if (!bpm)
  1034.                                         bpm = 1;
  1035.                                     if (bpm < 32) {
  1036.                                         x = 78125 * bpm;
  1037.                                         ticks = bpm;
  1038.                                         bpm = 768 / bpm;
  1039.                                     } else
  1040.                                         x = 60000000 / bpm;
  1041.                                     if (i)
  1042.                                         break; /* only write tempo on track 0 */
  1043.                                     cnt += 6 + WriteVLQ(f2, timer);
  1044.                                     timer = 0;
  1045.                                     OutByte(f2, 255); /* meta-event */
  1046.                                     OutByte(f2, 81); /* set tempo */
  1047.                                     OutByte(f2, 3);
  1048.                                     OutByte(f2, x >> 16);
  1049.                                     OutByte(f2, (x >> 8) & 0xFF);
  1050.                                     OutByte(f2, x & 0xFF);
  1051.                                     tempdone = 1;
  1052.                                     break;
  1053.                                 case 0xE00: /* extended effects */
  1054.                                     switch (effect & 0x0F0) {
  1055.                                         case 0x010: /* fine slide up */
  1056.                                             if (!(effect & 0x00F) || sam->m > 127)
  1057.                                                 break;
  1058.                                             if (!note)
  1059.                                                 if (!delay[k])
  1060.                                                     break;
  1061.                                                 else {
  1062.                                                     n[k][h][0] = lastn[k] + (effect & 0x00F);
  1063.                                                     n[k][h][1] = vol[k];
  1064.                                                 }
  1065.                                             else
  1066.                                                 n[k][h][0] += effect & 0x00F;
  1067.                                             break;
  1068.                                         case 0x020: /* fine slide down */
  1069.                                             if (!(effect & 0x00F) || sam->m > 127)
  1070.                                                 break;
  1071.                                             if (!note)
  1072.                                                 if (!delay[k])
  1073.                                                     break;
  1074.                                                 else {
  1075.                                                     n[k][h][0] = lastn[k] - (effect & 0x00F);
  1076.                                                     n[k][h][1] = vol[k];
  1077.                                                 }
  1078.                                             else
  1079.                                                 n[k][h][0] -= effect & 0x00F;
  1080.                                             break;
  1081.                                         case 0x000: /* set filter on/off */
  1082.                                         case 0x030: /* glissando on/off */
  1083.                                         case 0x040: /* set vibrato wave */
  1084.                                         case 0x050: /* set finetune */
  1085.                                         case 0x060: /* pattern loop */
  1086.                                         case 0x070: /* set tremolo wave */
  1087.                                         case 0x080: /* un-used */
  1088.                                         case 0x0F0: /* invert loop */
  1089.                                             /* can't do these in MIDI.. ignore */
  1090.                                             break;
  1091.                                         case 0x0A0: /* fine volume slide up */
  1092.                                         case 0x0B0: { /* fine volume slide down */
  1093.                                             int v;
  1094.  
  1095.                                             v = sam->v;
  1096.                                             if (effect & 0x0A0)
  1097.                                                 v += effect & 0x00F;
  1098.                                             else
  1099.                                                 v -= effect & 0x00F;
  1100.                                             if (v<0)
  1101.                                                 v = 0;
  1102.                                             else if (v>127)
  1103.                                                 v = 127;
  1104.                                             n[k][0][1] = v;
  1105.                                             break;
  1106.                                             }
  1107.                                         case 0x090: { /* retrigger sample */
  1108.                                             int a, b, c;
  1109.  
  1110.                                             if (!note && !delay[k] || !(effect & 0x00F))
  1111.                                                 break;
  1112.                                             a = effect & 0x00F;
  1113.                                             if (!(ticks / a))
  1114.                                                 break;
  1115.                                             if (!note) {
  1116.                                                 n[k][0][0] = lastn[k];
  1117.                                                 n[k][0][1] = vol[k];
  1118.                                             }
  1119.                                             c = 0;
  1120.                                             b = 1;
  1121.                                             a *= 48;
  1122.                                             while (c < 48) {
  1123.                                                 n[k][c][0] = note;
  1124.                                                 n[k][c][1] = n[k][0][1];
  1125.                                                 c = b * a / ticks;
  1126.                                                 b++;
  1127.                                             }
  1128.                                             break;
  1129.                                             }
  1130.                                         case 0x0C0: { /* cut sample */
  1131.                                             int a;
  1132.  
  1133.                                             if (!note && !delay[k])
  1134.                                                 break;
  1135.                                             a = 48 * (effect & 0x00F) / ticks;
  1136.                                             if (a > 47)
  1137.                                                 break;
  1138.                                             if (note)
  1139.                                                 n[k][a][0] = note;
  1140.                                             else
  1141.                                                 n[k][a][0] = lastn[k];
  1142.                                             n[k][a][1] = 0;
  1143.                                             break;
  1144.                                             }
  1145.                                         case 0x0D0: { /* delay sample */
  1146.                                             int a;
  1147.  
  1148.                                             if (!note || !(effect & 0x00F))
  1149.                                                 break;
  1150.                                             a = 48 * (effect & 0x00F) / ticks;
  1151.                                             n[k][0][0] = 0;
  1152.                                             if (a > 47)
  1153.                                                 break;
  1154.                                             n[k][a][0] = note;
  1155.                                             n[k][a][1] = n[k][a][0];
  1156.                                             break;
  1157.                                             }
  1158.                                         case 0x0E0: /* pattern pause */
  1159.                                             pause = 48 * (effect & 0x00F);
  1160.                                             break;
  1161.                                     }
  1162.                                     break;
  1163.                                 /* else dunno what it does.. disbelieve it ;) */
  1164.                             }
  1165.                         }
  1166.                     for (h = 0; h<48; h++) {
  1167.                         for (k = 0; k < 4; k++)
  1168.                             if (n[k][h][0]) {
  1169.                                 if (delay[k]) { /* turn off old note on same channel */
  1170.                                     cnt += 3 + WriteVLQ(f2, timer);
  1171.                                     timer = 0;
  1172.                                     OutByte(f2, 0x80 + c); /* note off */
  1173.                                     OutByte(f2, ENOTE(lastn[k], 0));
  1174.                                     OutByte(f2, vol[k]);
  1175.                                     if (sam->t[1]) {
  1176.                                         cnt += 4;
  1177.                                         OutByte(f2, 0);
  1178.                                         OutByte(f2, 0x80 + c);
  1179.                                         OutByte(f2, ENOTE(lastn[k], 1));
  1180.                                         OutByte(f2, vol[k]);
  1181.                                         if (sam->t[2]) {
  1182.                                             cnt += 4;
  1183.                                             OutByte(f2, 0);
  1184.                                             OutByte(f2, 0x80 + c);
  1185.                                             OutByte(f2, ENOTE(lastn[k], 2));
  1186.                                             OutByte(f2, vol[k]);
  1187.                                         }
  1188.                                     }
  1189.                                     delay[k] = 0;
  1190.                                 }
  1191.                                 lastn[k] = n[k][h][0];
  1192.                                 n[k][h][0] = 0;
  1193.                                 vol[k] = n[k][h][1];
  1194.                                 cnt += 3 + WriteVLQ(f2, timer);
  1195.                                 timer = 0;
  1196.                                 OutByte(f2, 0x90 + c); /* note on */
  1197.                                 OutByte(f2, ENOTE(lastn[k], 0));
  1198.                                 OutByte(f2, vol[k]);
  1199.                                 if (sam->t[1]) {
  1200.                                     cnt += 4;
  1201.                                     OutByte(f2, 0);
  1202.                                     OutByte(f2, 0x90 + c);
  1203.                                     OutByte(f2, ENOTE(lastn[k], 1));
  1204.                                     OutByte(f2, vol[k]);
  1205.                                     if (sam->t[2]) {
  1206.                                         cnt += 4;
  1207.                                         OutByte(f2, 0);
  1208.                                         OutByte(f2, 0x90 + c);
  1209.                                         OutByte(f2, ENOTE(lastn[k], 2));
  1210.                                         OutByte(f2, vol[k]);
  1211.                                     }
  1212.                                 }
  1213.                                 delay[k] = NoteLength(ANOTE(lastn[k]), sam->l, bpm);
  1214.                             } else if (delay[k]==1) {
  1215.                                 delay[k] = 0;
  1216.                                 cnt += 3 + WriteVLQ(f2, timer);
  1217.                                 timer = 0;
  1218.                                 OutByte(f2, 0x80 + c); /* note off */
  1219.                                 OutByte(f2, ENOTE(lastn[k], 0));
  1220.                                 OutByte(f2, vol[k]);
  1221.                                 if (sam->t[1]) {
  1222.                                     cnt += 4;
  1223.                                     OutByte(f2, 0);
  1224.                                     OutByte(f2, 0x80 + c);
  1225.                                     OutByte(f2, ENOTE(lastn[k], 1));
  1226.                                     OutByte(f2, vol[k]);
  1227.                                     if (sam->t[2]) {
  1228.                                         cnt += 4;
  1229.                                         OutByte(f2, 0);
  1230.                                         OutByte(f2, 0x80 + c);
  1231.                                         OutByte(f2, ENOTE(lastn[k], 2));
  1232.                                         OutByte(f2, vol[k]);
  1233.                                     }
  1234.                                 }
  1235.                             } else if (delay[k]>0)
  1236.                                 delay[k]--;
  1237.                         timer++;
  1238.                     }
  1239.                     timer += pause;
  1240.                     if (patbreak<0)
  1241.                         patbreak++;
  1242.                     else if (patbreak>0) {
  1243.                         patbreak = 1 - patbreak;
  1244.                         while (j) {
  1245.                             j--;
  1246.                             Inskipp(f1, 16); /* 16 bytes / song position */
  1247.                         }
  1248.                     }
  1249.                 }
  1250.             }
  1251.             for (k = 0; k < 4; k++)
  1252.                 if (delay[k]) {
  1253.                     cnt += 3 + WriteVLQ(f2, timer);
  1254.                     timer = 0;
  1255.                     OutByte(f2, 0x80 + c); /* note off */
  1256.                     OutByte(f2, ENOTE(lastn[k], 0));
  1257.                     OutByte(f2, vol[k]);
  1258.                     if (sam->t[1]) {
  1259.                         cnt += 4;
  1260.                         OutByte(f2, 0);
  1261.                         OutByte(f2, 0x80 + c);
  1262.                         OutByte(f2, ENOTE(lastn[k], 1));
  1263.                         OutByte(f2, vol[k]);
  1264.                         if (sam->t[2]) {
  1265.                             cnt += 4;
  1266.                             OutByte(f2, 0);
  1267.                             OutByte(f2, 0x80 + c);
  1268.                             OutByte(f2, ENOTE(lastn[k], 2));
  1269.                             OutByte(f2, vol[k]);
  1270.                         }
  1271.                     }
  1272.                 }
  1273.         }
  1274.         if (!i && !tempdone) {
  1275.             cnt += 7;
  1276.             OutByte(f2, 0); /* give the default 128 bpm if none done yet */
  1277.             OutByte(f2, 255);
  1278.             OutByte(f2, 81);
  1279.             OutByte(f2, 3);
  1280.             OutByte(f2, 7);
  1281.             OutByte(f2, 39);
  1282.             OutByte(f2, 14);
  1283.         }
  1284.         cnt += 3 + WriteVLQ(f2, timer);
  1285.         OutByte(f2, 255);
  1286.         OutByte(f2, 47);
  1287.         OutByte(f2, 0);
  1288.         AddToLog(inst, cnt); /* process this later */
  1289.         FGoto(f1, p2);
  1290.     }
  1291.     ClearWin();
  1292.     FlushOut(f2);
  1293.     WriteLog(f2->f);
  1294.     FGoto(f1, p1);
  1295. }
  1296.  
  1297. int main(int argc, char *argv[])
  1298. {
  1299.     int c;
  1300.  
  1301.     MainWindow("MIDIMOD - Amiga Noise/Sound/Protracker to MIDI converter",
  1302.         3, "File", 'f', "Samples", 's', "Help", 'h');
  1303.     SetMenu(0, 6, "Dest. midi",'d',0, "Source mod",'s',1, "------------",-1,-1,
  1304.         "Convert",'c',2, "------------",-1,-1, "Quit",'q',99);
  1305.     SetMenu(1, 4, "Map samples",'m',3, "Transposing",'t',6,
  1306.         "------------",-1,-1, "Save info",'s',4);
  1307.     SetMenu(2, 1, "About",'a',5);
  1308.     MidFile->f = ModFile->f = NULL;
  1309.     MidFN = ModFN = NULL;
  1310.     if (argc>2) {
  1311.         strcpy(MidFN = (string) malloc(strlen(argv[2])+1), argv[2]);
  1312.         if (fclose(fopen(MidFN, "r"))==EOF || tolower(InfoBox(_OUTE))=='y')
  1313.             OpenOut(MidFile, MidFN);
  1314.         if (MidFile==NULL) {
  1315.             free(MidFN);
  1316.             MidFN = NULL;
  1317.         }
  1318.     }
  1319.     if (argc>1) {
  1320.         strcpy(ModFN = (string) malloc(strlen(argv[1])+1), argv[1]);
  1321.         if (OpenIn(ModFile, ModFN))
  1322.             if (!ReadModSpecs(ModFile, SongName, Samples))
  1323.                 InfoBox(_MODE);
  1324.             else if (!SetDefaults(Samples, ModFN))
  1325.                 CloseIn(ModFile);
  1326.     }
  1327.     do {
  1328.         c = Choice();
  1329.         switch(c) {
  1330.             case 0:
  1331.                 MidFN = InitFile(MidFile, MidFN, "MIDI file below.", 0);
  1332.                 break;
  1333.             case 1:
  1334.                 if (ModFile->f != NULL)
  1335.                     SetDefaults(Samples, ModFN); /* make sure defaults are saved */
  1336.                 ModFN = InitFile(ModFile, ModFN, "MOD file below.", 1);
  1337.                 if (ModFN != NULL)
  1338.                     if (!ReadModSpecs(ModFile, SongName, Samples))
  1339.                         InfoBox(_MODE);
  1340.                     else if (!SetDefaults(Samples, ModFN))
  1341.                         CloseIn(ModFile);
  1342.                 break;
  1343.             case 2:
  1344.                 if (MidFile->f != NULL && ModFile->f != NULL)
  1345.                     if (ChooseChannels(Samples) <= 16)
  1346.                         ConvertMOD(ModFile, MidFile, SongName, Samples);
  1347.                     else
  1348.                         InfoBox(_TMC);
  1349.                 else
  1350.                     InfoBox(_CNVE);
  1351.                 break;
  1352.             case 3:
  1353.                 if (ModFile->f != NULL)
  1354.                     MapSamples(Samples);
  1355.                 else
  1356.                     InfoBox(_MODM);
  1357.                 break;
  1358.             case 4:
  1359.                 if (ModFile->f != NULL)
  1360.                     SaveSamples(Samples);
  1361.                 else
  1362.                     InfoBox(_MODM);
  1363.                 break;
  1364.             case 5:
  1365.                 InfoBox(_ABOUT);
  1366.                 break;
  1367.             case 6:
  1368.                 if (ModFile->f != NULL)
  1369.                     Transpositions(Samples);
  1370.                 else
  1371.                     InfoBox(_MODM);
  1372.                 break;
  1373.         }
  1374.     } while (c != 99);
  1375.     if (ModFile->f != NULL) {
  1376.         CloseIn(ModFile);
  1377.         SaveDefaults(Samples, ModFN);
  1378.     }
  1379.     free(ModFN);
  1380.     if (MidFile->f != NULL)
  1381.         CloseOut(MidFile);
  1382.     free(MidFN);
  1383.     return 0;
  1384. }
  1385.